package com.szholly.plug.activity.runtime;

import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Component;

import com.szholly.plug.activity.core.BpmException;
import com.szholly.plug.activity.core.Constants;
import com.szholly.utils.session.SessionFactory;
import com.szholly.utils.session.provider.ISessionProvider;
import com.szholly.utils.spring.SpringBeanFactory;
import com.szholly.utils.util.StringUtils;
import com.szholly.data.general.GlobalDataType;
import com.szholly.data.general.ITable;
import com.szholly.data.general.RowBase;
import com.szholly.data.general.interceptor.DbEditInterceptorClass;
import com.szholly.data.general.interceptor.DbEditType;
import com.szholly.data.general.interceptor.InterceptorRegister;
import com.szholly.plug.safe.entity.user.UserEntity;

/**
 * 定义工作流处理的数据拦截类 如此处理，可实现表单与工作流的独立
 */
@Component
public class WorkFlowEditInterceptor extends DbEditInterceptorClass {
	/**
	 * 注册拦截接口
	 */
	static {
		WorkFlowEditInterceptor interceptor = new WorkFlowEditInterceptor();
		InterceptorRegister.RegDbInterceptor(interceptor);
	}

	private IWorkFlowCompont workFlowCompont;
	private RuntimeService runtimeService;

	/**
	 * 获取对象
	 * 
	 * @return
	 */
	private IWorkFlowCompont getWorkFlowCompont() {
		if (workFlowCompont == null) {
			workFlowCompont = (IWorkFlowCompont) SpringBeanFactory
					.getBean(IWorkFlowCompont.class);
		}
		return workFlowCompont;
	}
	
	/**
	 * 获取对象
	 */
	private RuntimeService getRuntimeService() {
		if (runtimeService == null) {
			runtimeService = (RuntimeService) SpringBeanFactory
					.getBean(RuntimeService.class);
		}
		return runtimeService;
	}

	public WorkFlowEditInterceptor() {
		// 尽量最后一次执行
		super.setIndex(100000);
	}

	@Override
	public void BeforeDbEditOption(ITable table, Object editEntitys,
			DbEditType editType) {
		// 如果是新增，并且状态值为空，处理默认值
		if (editEntitys instanceof RowBase) {
			RowBase row = (RowBase) editEntitys;
			// 查看是否是工作流数据
			String activitiKey = (String) row.getValue(GlobalDataType.String,
					Constants.FIELD_ACTIVITIKEY);
			if (StringUtils.IsNullOrSpace(activitiKey)) {
				// 非工作流数据
				return;
			}

			ISessionProvider session = SessionFactory.getSession();
			UserEntity userEntity = (UserEntity) session
					.getObject(ISessionProvider.UserEntity);

			// 是否是工作流操作，默认为普通的数据保存
			String activitiSave = (String) row.getValue(GlobalDataType.String,
					Constants.FIELD_ACTIVITISAVE);
			// 获取流程实例ID
			String exeID = (String) row.getValue(GlobalDataType.String,
					Constants.FIELD_PROID);

			// 是否进行工作流保存
			if (StringUtils.IsNullOrSpace(activitiSave) || !activitiSave.equals("1")) {
				// 非工作流保存
				if (StringUtils.IsNullOrSpace(exeID)) {
					
					// 第一种规则：只保存数据，不启动流程
//					// 设置流程状态
//					row.setValue(Constants.FIELD_TASK_STATE, "草稿");
//					// 设置任务ID
//					row.setValue(Constants.FIELD_TASK_ID, "U0");
//					// 流程是否可删除
//					BpmTaskConfigRow configRow = BpmConfigCache.getTaskConfig(activitiKey, "U0");
//					if(configRow!=null){
//						row.setValue(Constants.FIELD_CANDEL, configRow.getTaskCanDel());
//					}else{
//						row.setValue(Constants.FIELD_CANDEL, "0");
//					}
					
					// 第二种规则：保存数据，并启动流程到第一个节点
					getWorkFlowCompont().onlyStart(table,row, userEntity, activitiKey);
				} else {
					// 后续保存
					checkProcessInstance(exeID);
				}
				return;
			}

			// 工作流保存
			if (editType == DbEditType.Delete) {
				delete(table, row, exeID, activitiKey, userEntity);
			} else if (editType == DbEditType.Insert
					|| editType == DbEditType.Update) {
				// 没有流程实例，则为启动流程
				if (StringUtils.IsNullOrSpace(exeID)) {
					getWorkFlowCompont().start(table,row, userEntity, activitiKey);
				} else {
					checkProcessInstance(exeID);
					
					// 工作流撤销 1 ： 撤销 2 ： 撤回 3 ： 交办
					String option = (String)row.getValue(GlobalDataType.String, Constants.FIELD_BPM_OPTION);
					if(StringUtils.IsNullOrSpace(option)){
						getWorkFlowCompont().complete(table,activitiKey, exeID, row, userEntity);
					} else if(option.equals("1")){
						getWorkFlowCompont().revoke(table,activitiKey, exeID, row, userEntity);
					} else if(option.equals("2")){
						getWorkFlowCompont().reback(table,activitiKey, exeID, row, userEntity);
					} else if(option.equals("3")){
						getWorkFlowCompont().assignedBy(table,activitiKey, exeID, row, userEntity);
					}
				}
			}
		}
	}

	private void delete(ITable table, RowBase row, String exeId, String activitiKey, UserEntity userEntity) {
		// 验证是否可编辑
		String canDel = (String) row.getValue(GlobalDataType.String,
				Constants.FIELD_CANDEL);
		if (StringUtils.IsNullOrSpace(canDel) || !canDel.equals("1")) {
			throw new BpmException("当前数据不可删除！原因：流程正在进行中！");
		}
		if(!StringUtils.IsNullOrSpace(exeId)){
			getWorkFlowCompont().revoke(table, activitiKey, exeId, row, userEntity);
		}
		if(row.containsKey(Constants.FIELD_ACTIVITIKEY)){
			row.remove(Constants.FIELD_ACTIVITIKEY);
		}
		if(row.containsKey(Constants.FIELD_ACTIVITISAVE)){
			row.remove(Constants.FIELD_ACTIVITISAVE);
		}
		if(row.containsKey(RowBase.FIELD_ISNEW)){
			row.remove(RowBase.FIELD_ISNEW);
		}
	}

	/**
	 * 验证工作流是否结束
	 * @param processID
	 */
	private void checkProcessInstance(String processID) {
		ProcessInstance processInstance = getRuntimeService()
			.createProcessInstanceQuery().processInstanceId(processID)
			.singleResult();
		if(processInstance==null){
			throw new BpmException("流程已经结束，不可再编辑数据");
		}
	}

	@Override
	public void DbEditOptionException(ITable table, Object editEntitys,
			DbEditType editType, Exception ex) {
	}

	@Override
	public void AfterDbEditOption(ITable table, Object editEntitys,
			DbEditType editType) {
	}

	@Override
	public String getInterceptorName() {
		return "定义工作流处理的数据拦截类";
	}
}